home *** CD-ROM | disk | FTP | other *** search
/ Visual Basic Toolbox / Visual Basic Toolbox (P.I.E.)(1996).ISO / clocks / ttcode / modblast.c < prev    next >
C/C++ Source or Header  |  1994-10-20  |  20KB  |  657 lines

  1. //---------------------------------------------------------------------------
  2. // modblast.c
  3. //---------------------------------------------------------------------------
  4. // Contains control procedure for ModBlaster control
  5. //---------------------------------------------------------------------------
  6.  
  7. #define  NOCOMM
  8. #include <windows.h>
  9.  
  10. #include <vbapi.h>
  11. #include <string.h>
  12. #define CTL_DATA
  13. #include "modblast.h"
  14.  
  15. //---------------------------------------------------------------------------
  16. // Global Variables
  17. //---------------------------------------------------------------------------
  18. HANDLE hmodDLL;
  19. CONTROLSTUFF controls[MAX_MSGBLASTERS];
  20. HANDLE taskDevEnvironment = NULL;
  21.  
  22.  
  23. //---------------------------------------------------------------------------
  24. // Utility Functions - added by BJ 1/15/94
  25. //---------------------------------------------------------------------------
  26. WORD FAR PASCAL _export mbLoWord(DWORD dword)
  27. {
  28.     return (WORD)dword;
  29. }
  30.     
  31. WORD FAR PASCAL _export mbHiWord(DWORD dword)
  32. {
  33.     return (WORD)(dword >> 16);
  34. }
  35.  
  36. WORD FAR PASCAL _export mbGetControlIndex(HWND hwnd)
  37. {
  38.     DWORD index;
  39.     HCTL hCtl;
  40.     if ((hCtl = VBGetHwndControl(hwnd)) && 
  41.         (VBGetControlProperty(hCtl, IPROP_STD_INDEX, (LPVOID)&index) == 0))
  42.         return (WORD)index;
  43.     else
  44.         return (WORD)-1;
  45. }
  46.  
  47. ULONG FAR PASCAL _export mbSetControlFlags(HWND hwnd, ULONG mask, ULONG value)
  48. {
  49.     return VBSetControlFlags(VBGetHwndControl(hwnd), mask, value);
  50. }
  51.  
  52. //---------------------------------------------------------------------------
  53. // MsgBlaster Control Procedure
  54. //---------------------------------------------------------------------------
  55. LONG FAR PASCAL _export MsgBlasterCtlProc(HCTL hctl, HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
  56. {
  57.       switch (msg)
  58.     { 
  59.         
  60.     case WM_NCCREATE:
  61.     {
  62.         int i;
  63.         // deref MsgBlaster control struct now - valid until we call VB procedure (BJ)
  64.         PMSGBLASTER lpMsgBlaster = LpblastDEREF(hctl);
  65.         
  66.         // Look for an open slot in the array and save the hctl
  67.         for(i = 0; i < MAX_MSGBLASTERS; i++)
  68.         {
  69.             if(controls[i].hctlMain == NULL)
  70.             {
  71.                 controls[i].hctlMain = hctl;
  72.                 break;
  73.             }
  74.         }
  75.         
  76.         // If users are trying to use this many blasters, then they are 
  77.         // probably doing something wrong. Besides, using 25 blasters would
  78.         // slow down the entire system
  79.         if (i == MAX_MSGBLASTERS)
  80.         {
  81.             MessageBox(hwnd, "Too many message blasters", "Error!", MB_OK);
  82.             return(0);
  83.         }
  84.  
  85.         // make sure that the hWndTargets are zeroed out.
  86.         lpMsgBlaster->hWndTarget = NULL;
  87.  
  88.         // initialize the passage var to pass msgs onto the origproc
  89.         // after firing the event. This is the default behavior.
  90.         // There was a bug here - replaced MAX_MSGBLASTERS with MAX_TRAPPABLEMSGS (BJ)
  91.         for(i = 0; i < MAX_TRAPPABLEMSGS; i++)
  92.             lpMsgBlaster->MsgPassage[i] = 1;
  93.  
  94.           VBSetControlProperty(hctl, IPROP_MSGBLASTER_ABOUTBOX, 
  95.               (LONG)(LPSTR)"Click on \"...\" for the About Box ---->");
  96.  
  97.     }
  98.     break;
  99.  
  100.     case VBM_SETPROPERTY:
  101.         switch(wp)
  102.         {
  103.         case IPROP_MSGBLASTER_HWNDTARGET:
  104.         {
  105.             int i, j;
  106.             
  107.             // we only process this message if we are in run mode
  108.             if (VBGetMode() != MODE_DESIGN)
  109.             {   
  110.                 // deref MsgBlaster control struct now - valid until we call VB procedure (BJ)
  111.                 PMSGBLASTER lpMsgBlaster = LpblastDEREF(hctl);
  112.                 
  113.                 // find the next slot and save the hWndTarget
  114.                 for(i = 0; i < MAX_MSGBLASTERS; i++)
  115.                 {
  116.                     if(controls[i].hctlMain == hctl)
  117.                     {
  118.                         // Check to see if this blaster is already being
  119.                         // used to subclass a control
  120.                         // if it is, un-subclass it.
  121.                         // This could happen when the vb programmer changes
  122.                         // the target control at run time
  123.                         if(controls[i].hWndTarget) {
  124.                             UnSubClass(controls[i].hWndTarget,hctl);
  125.                             // initialize messages and passage when target changes (BJ)
  126.                             for(j = 0; j < MAX_TRAPPABLEMSGS; j++) {
  127.                                 lpMsgBlaster->MsgList[j] = 0;
  128.                                 lpMsgBlaster->MsgPassage[j] = 1;
  129.                             }
  130.                         }        
  131.  
  132.                         controls[i].hWndTarget = (HWND)lp;
  133.                         break;
  134.                     }
  135.                 }
  136.                 
  137.                 // sublcass the target control
  138.                 // only if target not == NULL (BJ)
  139.                 if ((HWND)lp != NULL && !FSubClass((HWND)lp))
  140.                     MessageBox(hwnd, "Unable to subclass control", "Error", MB_OK);
  141.             }
  142.         }
  143.         return 0L;
  144.  
  145.         case IPROP_MSGBLASTER_MSGLIST:
  146.         {                                                 
  147.             // This is where we store the list of messages to trap
  148.             // normally, the vb programmer will load this in the 
  149.             // form load event.
  150.             LONG i;
  151.             LPDATASTRUCT lpDs = (LPDATASTRUCT)lp;
  152.  
  153.             i = lpDs->index[0].data;
  154.             
  155.             // I put an arbitrary limit on the number of messages 
  156.             // that could be trapped. My think is that they really shouldn't
  157.             // be doing a lot of message processing in VB.
  158.             if (i < 0 || i >= MAX_TRAPPABLEMSGS)
  159.                 return ERRBADINDEX;
  160.  
  161.                         LpblastDEREF(hctl)->MsgList[i] = (UINT)lpDs->data;
  162.             return 0L;
  163.         }
  164.  
  165.         case IPROP_MSGBLASTER_MSGPASSAGE:
  166.         {                      
  167.             // This property determines how each message will be processed
  168.             // There are 3 valid possibilities; -1, 0, 1. 
  169.             // -1 means preprocess the message. This means pass it on to the
  170.             //      VBDefControlProc first 
  171.             // 0  means eat the message. i.e. never pass it on
  172.             // 1 means pass the message on after firing the event
  173.             // This is the default.
  174.             LONG i;
  175.             LPDATASTRUCT lpDs = (LPDATASTRUCT)lp;
  176.  
  177.             i = lpDs->index[0].data;
  178.             if (i < 0 || i >= MAX_TRAPPABLEMSGS)
  179.                 return ERRBADINDEX;
  180.  
  181.             LpblastDEREF(hctl)->MsgPassage[i] = (SHORT)lpDs->data;
  182.             return 0L;
  183.         }
  184.  
  185.     }
  186.     break;
  187.  
  188.  
  189.     case VBM_GETPROPERTY:
  190.         switch(wp)
  191.         {
  192.         case IPROP_MSGBLASTER_MSGLIST:
  193.         {
  194.             LONG i;
  195.             LPDATASTRUCT lpDs = (LPDATASTRUCT)lp;
  196.  
  197.             i = lpDs->index[0].data;
  198.             if (i < 0 || i >= MAX_TRAPPABLEMSGS)
  199.                 return ERRBADINDEX;
  200.  
  201.                         lpDs->data = (LONG)LpblastDEREF(hctl)->MsgList[i];
  202.             return 0L;
  203.         }
  204.         case IPROP_MSGBLASTER_MSGPASSAGE:
  205.         {
  206.             LONG i;
  207.             LPDATASTRUCT lpDs = (LPDATASTRUCT)lp;
  208.  
  209.             i = lpDs->index[0].data;
  210.             if (i < 0 || i >= MAX_TRAPPABLEMSGS)
  211.                 return ERRBADINDEX;
  212.  
  213.             lpDs->data = LpblastDEREF(hctl)->MsgPassage[i];
  214.             return 0L;
  215.         }
  216.         case IPROP_MSGBLASTER_HWNDTARGET:
  217.         {
  218.             LONG i;
  219.             LPDATASTRUCT lpDs = (LPDATASTRUCT)lp;
  220.  
  221.             i = lpDs->index[0].data;
  222.             if (i < 0 || i >= MAX_TRAPPABLEMSGS)
  223.                 return ERRBADINDEX;
  224.  
  225.             lpDs->data = LpblastDEREF(hctl)->hWndTarget;
  226.             return 0L;
  227.         }
  228.  
  229.         } // end of switch
  230.         break;
  231.  
  232.         case VBM_INITPROPPOPUP:
  233.                if(wp == IPROP_MSGBLASTER_ABOUTBOX)
  234.             {
  235.                 HWND hwndList = (HWND)LOWORD(lp);
  236.                 return (LONG)HwndInitAboutBox();
  237.             }
  238.             break;
  239.         case IPROP_MSGBLASTER_ABOUTBOX:
  240.             // force a repaint
  241.             InvalidateRect(hwnd, NULL, FALSE);
  242.             break;
  243.  
  244.         case WM_NCDESTROY:
  245.             if(LpblastDEREF(hctl)->hszAbout)
  246.                 VBDestroyHsz(LpblastDEREF(hctl)->hszAbout);
  247.             break;
  248.  
  249.         case WM_DESTROY:
  250.         {
  251.             int i;
  252.  
  253.             // find which control we are dealing with
  254.             for(i = 0; i < MAX_MSGBLASTERS; i++)
  255.                 if(controls[i].hctlMain == hctl)
  256.                     break;
  257.  
  258.             // ****>>> We *must* unsubclass the hwndTarget when 
  259.             // this hctl goes away!
  260.             UnSubClass(controls[i].hWndTarget,hctl);
  261.  
  262.             controls[i].hWndTarget = NULL;
  263.             controls[i].hctlMain = NULL;
  264.         }
  265.         break;
  266.     }
  267.     return VBDefControlProc(hctl, hwnd, msg, wp, lp);
  268. }
  269.  
  270.  
  271. //---------------------------------------------------------------------------
  272. // Sub class routine for target control window proc.
  273. //---------------------------------------------------------------------------
  274. LONG FAR PASCAL _export SubClassProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
  275. {
  276.       LONG rc;
  277.       int  i, j;
  278.     UINT m;
  279.     HCTL hctlMain;
  280.  
  281.     // find the correct hctlMain
  282.     // I could have called FindhctlMain, but I wanted to avoid the overhead
  283.     // we need the most speed we can get in this routine.
  284.     for(j = 0; j < MAX_MSGBLASTERS; j++)
  285.         if(controls[j].hWndTarget == hwnd)
  286.             break;
  287.  
  288.     // The first part of this if is a sanity check
  289.     if(j == MAX_MSGBLASTERS)
  290.         MessageBox(hwnd, "Big trouble. We're gonna die.", "TROUBLE", MB_OK);
  291.     else
  292.         hctlMain = controls[j].hctlMain;
  293.  
  294.         for (i=0; i < MAX_TRAPPABLEMSGS; i++)
  295.     {
  296.  
  297.         // Get out of the loop if hctlMain is no longer valid
  298.         // ****>>> Since you fire an event, it is possible for hctlMain to
  299.         // disappear during that event, so you must check to see if hctlMain
  300.         // is still non-NULL.  This is also why I added the NULLing out of
  301.         // this variable to the WM_DESTROY case.
  302.         if (!hctlMain)
  303.               break;
  304.  
  305.         // ****>>> Firing an event invalidates pMsgBlaster!!!!    
  306.         // You MUST deref it each time through this loop!!!
  307.                 m = LpblastDEREF(hctlMain)->MsgList[i];
  308.  
  309.         // Get out of the loop if no more messages
  310.         if (!m)
  311.               break;
  312.  
  313.         if (msg == m)
  314.         {
  315.             int eat;
  316.  
  317.             // now that we have a hit, determine if we should pass the
  318.             // msg on to the orig proc first, last or
  319.             // do we eat the msg entirely
  320.             eat = LpblastDEREF(hctlMain)->MsgPassage[i];
  321.             switch(eat)
  322.             {
  323.             case -1: // call the orig proc first
  324.                 rc = CallWindowProc(LpblastDEREF(hctlMain)->lpfnOrigProc,
  325.                                 hwnd, msg, wp, lp);
  326.                 rc = FireMessage(hctlMain, msg, wp, lp, rc);
  327.                 if (msg == WM_DESTROY)
  328.                 {
  329.                     MessageBox(hwnd,
  330.                         "Can't call original proc with WM_DESTROY prior to firing event.",
  331.                         "Error", MB_OK);
  332.                     break;
  333.                 }
  334.                 return rc;
  335.  
  336.             case 0: // eat the message
  337.                 rc = FireMessage(hctlMain, msg, wp, lp, rc);
  338.                 if (msg == WM_DESTROY)
  339.                 {
  340.                     MessageBox(hwnd,
  341.                         "Can't eat WM_DESTROY message.",
  342.                         "Error", MB_OK);
  343.                     break;
  344.                 }
  345.                 return rc;
  346.  
  347.             case 1: // pass it on afterward
  348.                 rc = FireMessage(hctlMain, msg, wp, lp, rc);
  349.                 break;
  350.  
  351.             case 2: // pass it on afterward - MAYBE - BJ
  352.                 rc = FireMessage(hctlMain, msg, wp, lp, rc);
  353.                 // if the return code is 0 then the message has been handled - BJ
  354.                 if (rc == 0) return rc;
  355.                 break;
  356.  
  357.             default:
  358.                 MessageBox(hwnd,
  359.                     "Default case in passage test. Should never get.",
  360.                         "Error", MB_OK);
  361.                 break;
  362.             }
  363.         }
  364.     }
  365.  
  366.       // Call the original Window Procedure
  367.       rc = CallWindowProc(LpblastDEREF(hctlMain)->lpfnOrigProc, hwnd, msg, wp, lp);
  368.  
  369.       // ****>>> Strictly speaking, it is not necessary to unsubclass this window
  370.       // since it is being destroyed, but UnSubClass() does *need* to reset the
  371.       // necessary global variables, and modular programming says we shouldn't
  372.       // do that from here, when UnSubClass() can do that for us...
  373.       if (msg == WM_DESTROY)
  374.         UnSubClass(hwnd, hctlMain);
  375.  
  376.       return rc;
  377. }
  378.  
  379.  
  380. //--------------------------------------------------------------------------
  381. // Fire the msg event
  382. //--------------------------------------------------------------------------
  383. LONG NEAR FireMessage(HCTL hctl, UINT m, WPARAM wp, LPARAM lp, LONG rc)
  384. {
  385.     MSGPARAMS p;
  386.     UINT mval = m;      
  387.     
  388.     p.MsgVal = &mval;
  389.     p.wParam = ℘
  390.     p.lParam = &lp;
  391.     p.lRetVal= &rc;
  392.  
  393.     VBFireEvent(hctl, IEVENT_MSGBLASTER_MSG, &p);
  394.     return rc;
  395. }
  396.  
  397.  
  398. //---------------------------------------------------------------------------
  399. // Register custom control.  This routine is called by VB when the custom
  400. // control DLL is loaded for use.
  401. //---------------------------------------------------------------------------
  402. BOOL FAR PASCAL _export VBINITCC(USHORT usVersion, BOOL fRuntime)
  403. {
  404.     // Avoid warnings on unused (but required) formal parameters
  405.     fRuntime  = fRuntime;
  406.  
  407.     // Register control(s)
  408.     if (usVersion < VB200_VERSION)
  409.       return FALSE;
  410.  
  411.     // Register popup class if this is from the development environment.
  412.     if (!fRuntime)
  413.     {
  414.     WNDCLASS class;
  415.  
  416.     class.style        = 0;
  417.     class.lpfnWndProc   = AboutBoxProc;
  418.     class.cbClsExtra    = 0;
  419.     class.cbWndExtra    = 0;
  420.     class.hInstance     = hmodDLL;
  421.     class.hIcon            = NULL;
  422.     class.hCursor        = NULL;
  423.     class.hbrBackground = NULL;
  424.     class.lpszMenuName  = NULL;
  425.     class.lpszClassName = CLASS_ABOUTBOX;
  426.  
  427.     if (!RegisterClass(&class))
  428.         return FALSE;
  429.  
  430.     // Remember the task associated with the development environment
  431.     taskDevEnvironment = GetCurrentTask();
  432.  
  433.     }
  434.  
  435.  
  436.     return VBRegisterModel(hmodDLL, &modelMsgBlaster);
  437. }
  438.  
  439.  
  440. //---------------------------------------------------------------------------
  441. // Provide custom control model information to host environment.
  442. //---------------------------------------------------------------------------
  443. LPMODELINFO FAR PASCAL _export VBGetModelInfo(USHORT usVersion)
  444. {
  445.     if (usVersion < VB200_VERSION)
  446.         return NULL;
  447.     else
  448.         return &modelinfoMsgBlaster;
  449. }
  450.  
  451.  
  452. //---------------------------------------------------------------------------
  453. // Initialize library.    This routine is called when the first client loads
  454. // the DLL.
  455. //---------------------------------------------------------------------------
  456. int FAR PASCAL LibMain(HANDLE hModule, WORD wDataSeg, WORD cbHeapSize, LPSTR lpszCmdLine)
  457. {
  458.     // Avoid warnings on unused (but required) formal parameters
  459.     wDataSeg    = wDataSeg;
  460.     cbHeapSize    = cbHeapSize;
  461.     lpszCmdLine = lpszCmdLine;
  462.  
  463.     hmodDLL = hModule;
  464.  
  465.     return 1;
  466. }
  467.  
  468. //---------------------------------------------------------------------------
  469. // Unregister the property popup , if this unload
  470. //    is from the development environment.
  471. //---------------------------------------------------------------------------
  472.  
  473. VOID FAR PASCAL _export VBTERMCC()
  474. {
  475.     // Unregister popup class if this is from the development environment
  476.     if (taskDevEnvironment == GetCurrentTask())
  477.     {
  478.         UnregisterClass(CLASS_ABOUTBOX, hmodDLL);
  479.         taskDevEnvironment = NULL;
  480.     }
  481. }
  482.  
  483. //---------------------------------------------------------------------------
  484. // WEP
  485. //---------------------------------------------------------------------------
  486. // C7 and QCWIN provide default a WEP:
  487. //---------------------------------------------------------------------------
  488. #if (_MSC_VER < 610)
  489.  
  490. int FAR PASCAL WEP(int fSystemExit);
  491.  
  492. //---------------------------------------------------------------------------
  493. // For Windows 3.0 it is recommended that the WEP function reside in a
  494. // FIXED code segment and be exported as RESIDENTNAME.  This is
  495. // accomplished using the alloc_text pragma below and the related EXPORTS
  496. // and SEGMENTS directives in the .DEF file.
  497. //
  498. // Read the comments section documenting the WEP function in the Windows
  499. // 3.1 SDK "Programmers Reference, Volume 2: Functions" before placing
  500. // any additional code in the WEP routine for a Windows 3.0 DLL.
  501. //---------------------------------------------------------------------------
  502. #pragma alloc_text(WEP_TEXT,WEP)
  503.  
  504. //---------------------------------------------------------------------------
  505. // Performs cleanup tasks when the DLL is unloaded.  WEP() is
  506. // called automatically by Windows when the DLL is unloaded (no
  507. // remaining tasks still have the DLL loaded).    It is strongly
  508. // recommended that a DLL have a WEP() function, even if it does
  509. // nothing but returns success (1), as in this example.
  510. //---------------------------------------------------------------------------
  511. int FAR PASCAL WEP(int fSystemExit)
  512. {
  513.     // Avoid warnings on unused (but required) formal parameters
  514.     fSystemExit = fSystemExit;
  515.  
  516.     return 1;
  517. }
  518. #endif
  519.  
  520. //---------------------------------------------------------------------------
  521. // ****>>> Aux fn to subclass only valid windows, and only when we're not
  522. // already subclassing a window.  Takes care of setting up and maintaining
  523. // the two necessary globals.  Returns TRUE if it actually subclassed, FALSE
  524. // otherwise.
  525. //---------------------------------------------------------------------------
  526. BOOL FSubClass(HWND hwnd)
  527. {
  528.     int i;
  529.     HCTL hctlMain;
  530.  
  531.       if (!IsWindow(hwnd))
  532.         return(FALSE);    // Invalid hwnd parameter
  533.  
  534.     hctlMain = FindhctlMain(hwnd);
  535.     if(!hctlMain)
  536.         return(FALSE);
  537.  
  538.  
  539.       if(i < MAX_MSGBLASTERS)
  540.           if (LpblastDEREF(hctlMain)->lpfnOrigProc)
  541.             return FALSE;    // Already are subclassing
  542.  
  543.       LpblastDEREF(hctlMain)->lpfnOrigProc =
  544.           (FARPROC)SetWindowLong(hwnd, GWL_WNDPROC, (DWORD)SubClassProc);
  545.  
  546.     return TRUE;
  547. }
  548.  
  549.  
  550. //---------------------------------------------------------------------------
  551. // ****>>> Undo what FSubClass() did.  Takes car of clearing out the two
  552. // necessary globals.
  553. //---------------------------------------------------------------------------
  554. VOID UnSubClass(HWND hWndTarget, HCTL hctlMain)
  555. {
  556.     PMSGBLASTER pMsgBlaster;
  557.  
  558.     pMsgBlaster = LpblastDEREF(hctlMain);
  559.  
  560.       // Make sure we're actually subclassing before we undo it.        if (pMsgBlaster->lpfnOrigProc)
  561.     {
  562.         SetWindowLong(hWndTarget, GWL_WNDPROC, (LONG)pMsgBlaster->lpfnOrigProc);
  563.         pMsgBlaster->lpfnOrigProc = 0L;
  564.         pMsgBlaster->hWndTarget = NULL;
  565.     }
  566. }
  567.  
  568. HCTL FindhctlMain(HWND hWnd)
  569. {
  570.     int j;
  571.  
  572.     // find the correct hctlMain
  573.       for(j = 0; j < MAX_MSGBLASTERS; j++)
  574.     {
  575.         if(controls[j].hWndTarget == hWnd)
  576.             break;
  577.     }
  578.  
  579.     return(j == MAX_MSGBLASTERS ? NULL:controls[j].hctlMain);
  580. }
  581.  
  582.  
  583. //---------------------------------------------------------------------------
  584. // Create our property popup-window.  Since we want to put up a dialog, this
  585. // window never becomes visible.  Instead, when asked to become visible, it
  586. // will post a message to itself, remining it to put up our dialog.
  587. //
  588. // NOTE: May return NULL!
  589. //---------------------------------------------------------------------------
  590. HWND NEAR HwndInitAboutBox(VOID)
  591. {
  592.     return(CreateWindow(CLASS_ABOUTBOX, NULL, WS_POPUP,
  593.             0, 0, 0, 0, NULL, NULL,
  594.             hmodDLL, NULL));
  595. }
  596.  
  597. //---------------------------------------------------------------------------
  598. // We asked to show ourself, remain invisible and post a CM_OPENABOUT to
  599. // ourself.  When we receive this message, open the dialog box.
  600. //---------------------------------------------------------------------------
  601. LONG _export FAR PASCAL AboutBoxProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
  602. {
  603.  
  604.     switch (msg)
  605.     {
  606.     case WM_SHOWWINDOW:
  607.         if (wParam)
  608.         {
  609.             PostMessage(hWnd, CM_OPENABOUTBOX, 0, 0L);
  610.             return 0L;
  611.         }
  612.         break;
  613.  
  614.     case CM_OPENABOUTBOX:
  615.         VBDialogBoxParam(hmodDLL, "AboutBox", (FARPROC)AboutBoxDlgProc, 0L);
  616.         return 0L;
  617.     }
  618.  
  619.     return DefWindowProc(hWnd, msg, wParam, lParam);
  620. }
  621.  
  622.  
  623. //---------------------------------------------------------------------------
  624. // The Dialog Procedure for the AboutBox dialog.
  625. //---------------------------------------------------------------------------
  626. BOOL FAR PASCAL _export AboutBoxDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
  627. {
  628.     switch (msg)
  629.     {
  630.     case WM_INITDIALOG:
  631.     {
  632.         RECT rect;
  633.         int  nx, ny;      // New x and y
  634.         int  width, height;
  635.  
  636.         // Position dialog so it looks nice:
  637.         GetWindowRect(hDlg, &rect);
  638.         width  = rect.right - rect.left;
  639.         height = rect.bottom - rect.top;
  640.         nx = (GetSystemMetrics(SM_CXSCREEN) - width)  / 2;
  641.         ny = (GetSystemMetrics(SM_CYSCREEN) - height) / 3;
  642.         MoveWindow(hDlg, nx, ny, width, height, FALSE);
  643.         return TRUE;
  644.     }
  645.  
  646.     case WM_COMMAND:
  647.         if(wParam ==  IDOK)
  648.         {
  649.             EndDialog(hDlg, TRUE);
  650.             return TRUE;
  651.         }
  652.     }
  653.     return FALSE;
  654. }
  655.  
  656. //-- EOF -------------------------------------------------------------------
  657.